package com.suifeng.card.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.zvo.email.Email;
import com.google.gson.Gson;
import com.suifeng.card.dao.SocialDao;
import com.suifeng.card.dao.UserRolesRoleDao;
import com.suifeng.card.entity.Social;
import com.suifeng.card.entity.User;
import com.suifeng.card.dao.UserDao;
import com.suifeng.card.entity.UserRolesRole;
import com.suifeng.card.redis.RedisUtil;
import com.suifeng.card.service.UserService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * (User)表服务实现类
 *
 * @author makejava
 * @since 2025-07-26 19:47:46
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {

    private static final String LOGIN_PREFIX = "loginCode";

    private static final String authRolePrefix = "auth.role";

    private static final String salt = "suifeng";

    @Resource
    private UserDao userDao;

    @Resource
    private UserRolesRoleDao userRolesRoleDao;

    @Resource
    private SocialDao socialDao;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public User queryByuserName(User user) {
        return this.userDao.queryByuserName(user);
    }

    /**
     * 注册用户
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(User user) {
        //校验用户是否存在
        User user1 = queryByuserName(user);
        if (Objects.nonNull(user1)) {
            return false;
        }
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(SaSecureUtil.md5BySalt(user.getPassword(), salt));
        }
        this.userDao.insert(user);
        insertSocial(user);

        UserRolesRole userRolesRole = new UserRolesRole();
        userRolesRole.setUserid(user.getId());
        userRolesRole.setRoleid(3);
        this.userRolesRoleDao.insert(userRolesRole);
        //缓存角色信息
        String roleKey = redisUtil.buildKey(authRolePrefix, user.getUsername());
        List<UserRolesRole> roleList = new LinkedList<>();
        roleList.add(userRolesRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));
        return true;
    }

    private void insertSocial(User user) {
        Social social = new Social();
        social.setUserid(user.getId());
        social.setEnable(1);
        if (user.getEmail() != null) {
            social.setName("email");
            social.setValue(user.getEmail());
            this.socialDao.insert(social);
        } else {
            social.setName("email");
            this.socialDao.insert(social);
        }
        if (user.getPhone() != null) {
            social.setName("phone");
            social.setValue(user.getPhone());
            this.socialDao.insert(social);
        } else {
            social.setName("phone");
            this.socialDao.insert(social);
        }
    }

    @Override
    public Boolean sendEmail(User user) {
        String host = "smtp.163.com";
        String username = "suifeng@163.com"; //您的163邮箱
        String password = "授权码";
        Email mail = new Email(host, username, password); //创建
        String email = user.getEmail();
        Random random = new Random();
        int verificationCode = random.nextInt(900000) + 100000;
        String codeKey = redisUtil.buildKey(LOGIN_PREFIX, user.getEmail());
        redisUtil.setNx(codeKey, String.valueOf(verificationCode), 5L, TimeUnit.MINUTES);
        String CodeContent = "【card】您的注册验证码为：" + verificationCode + "该验证码5分钟内有效，请及时验证。";
        mail.sendHtmlMail(email, "【card】验证你的电子邮件地址", CodeContent);
        return true;
    }

    @Override
    public String getEmailcaptcha(User user) {
        String result = redisUtil.get(redisUtil.buildKey(LOGIN_PREFIX, String.valueOf(user.getEmail())));
        return result;
    }

    /**
     * username不能重复
     *
     * @param user
     * @return
     */
    public SaTokenInfo ulogin(User user) {
        if (StringUtils.isBlank(user.getUsername())) {
            return null;
        } else if (StringUtils.isBlank(user.getPassword())) {
            return null;
        }
        User checkUser = new User();
        checkUser.setUsername(user.getUsername());
        User result = userDao.queryByuserName(checkUser);
        if (user.getPassword().equals(result.getPassword()) && user.getCode().equals(this.getEmailcaptcha(user))) {
            StpUtil.login(user.getUsername());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return tokenInfo;
        }
        return null;
    }

    /**
     * 邮箱登录
     *
     * @param user
     * @return
     */
    public SaTokenInfo elogin(User user) {
        if (StringUtils.isBlank(user.getEmail()) || StringUtils.isBlank(user.getCode())) {
            return null;
        }
        String tEmail = redisUtil.buildKey(LOGIN_PREFIX, user.getEmail());
        String code = redisUtil.get(tEmail);
        if (StringUtils.isBlank(code)) {
            return null;
        } else if (code.equals(user.getCode())) {
            StpUtil.login(user.getEmail());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            log.info("登录成功！token{}", tokenInfo.getTokenValue());
            return tokenInfo;
        }
        return null;
    }
}
